﻿using System;
using System.Collections.Generic;
using MyHealthByDesign.Domain;
using MyHealthByDesign.Properties;

namespace MyHealthByDesign.DataAccess.AccountDA
{
    /// <summary>
    /// Description:
    /// AccountRepository class provides core data services to the domain class.
    /// 
    /// Author: Sanjeev Shrestha
    /// Date Created: 10/17/2011
    /// 
    /// Other code files referenced:
    /// AccountDao.cs
    /// 
    /// Regression Test Information:
    /// AccountRepository_Test.cs in project MyHealthByDesign_Test
    /// 
    /// Revision History:
    /// 10/20/2011 Sanjeev Shrestha - Renamed username text to email. Added user object in session variable.
    /// 10/21/2011 Sanjeev Shrestha - Updated code to register new user in database.
    /// 10/27/2011 Mark Servais - Added methods for Question database processing
    /// 10/27/2011 Sanjeev Shrestha - Added methods for Question maintenance
    /// 10/30/2011 Mark Servais - Added method to allow submission of answers
    /// 11/03/2011 Mark Servais - Added methods to retreive certification date, determine if answers are certified
    ///                             and added method to retrieve question answers by field name
    /// 11/08/2011 Mark Servais - Made changes to retreive user and bring back Identity value to populate in user object.
    /// 12/02/2011 Mark Servais - Added routines for category maintenance
    /// 12/03/2011 Mark Servais - Added routines for question maintenance
    /// 12/10/2011 Mark Servais - Added routines for option maintenance
    /// 
    /// Known Faults:
    /// None.
    /// </summary>
    public class AccountRepository
    {
        private string connectionString = Settings.Default.MyHealthByDesignDB;
        private AccountDao accountDao;

        /// <summary>
        /// Class Constructor
        /// 
        /// PreConditions:
        /// None
        /// 
        /// PostConditions:
        /// Class AccountRepository is created
        /// </summary>
        public AccountRepository()
        {
            accountDao = new AccountDao(connectionString);
        }

        /// <summary>
        /// GetUser - Retireves User object
        /// 
        /// PreConditions:
        /// None
        /// 
        /// PostConditions:
        /// User object is returned based on parameters passed
        /// </summary>
        /// <param name="username"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public User GetUser(string username, string password)
        {
            User user;

            try
            {
                user = accountDao.GetUserInfo(username, password);
            }
            catch (Exception ex)
            {
                user = null;
            }

            return user;
        }

        /// <summary>
        /// GetPassword - Retireves User password based on email
        /// 
        /// PreConditions:
        /// None
        /// 
        /// PostConditions:
        /// String representing password is returned
        /// </summary>
        /// <param name="email"></param>
        /// <returns></returns>
        public string GetPassword(string email)
        {
            string password;

            try
            {
                password = accountDao.GetPassword(email);
            }
            catch (Exception ex)
            {
                password = string.Empty;
            }

            return password;
        }

        /// <summary>
        /// RegsiterUser - Creates a new user in the database
        /// 
        /// PreConditions:
        /// User does not already exist via provided email
        /// 
        /// PostConditions:
        /// Integer value that represents the UserID in the database
        /// </summary>
        /// <param name="lastname"></param>
        /// <param name="firstname"></param>
        /// <param name="birthDate"></param>
        /// <param name="city"></param>
        /// <param name="state"></param>
        /// <param name="zipCode"></param>
        /// <param name="email"></param>
        /// <param name="password"></param>
        /// <param name="mobile"></param>
        /// <param name="textFlag"></param>
        /// <param name="sex"></param>
        /// <param name="ethnicity"></param>
        /// <returns></returns>
        public int RegisterUser(string lastname, string firstname, string birthDate, string city, string state, string zipCode, string email, string password, string mobile, string textFlag, string sex, string ethnicity)
        {
            int insertId = 0;
            try
            {
                insertId = accountDao.RegsiterUser(lastname, firstname, birthDate, city, state, zipCode, email, password, mobile, textFlag,
                                                          sex, ethnicity);
            }
            catch (Exception)
            {
                insertId = 0;
            }

            return insertId;
        }

        /// <summary>
        /// GetQuestions - Retrieves all Questions from the database
        /// related to the provided categoryId value
        /// 
        /// PreConditions:
        /// Category needs to exist in the system
        /// 
        /// PostConditions:
        /// List of questions objects is returned
        /// </summary>
        /// <param name="categoryId"></param>
        /// <returns></returns>
        public List<Question> GetQuestions(int categoryId)
        {
            try
            {
                return accountDao.GetQuestionsForCategory(categoryId);
            }
            catch (Exception)
            {
                return  new List<Question>();
            }

        }

        /// <summary>
        /// AnswersRecorded - Adds a question answer for a user
        /// to the database
        /// 
        /// PreConditions:
        /// User must exist in the system
        /// 
        /// PostConditions:
        /// Returns boolean value if answers were added successfully
        /// </summary>
        /// <param name="lstQuestionAnswers"></param>
        /// <returns></returns>
        public bool AnswersRecorded(List<QuestionAnswer> lstQuestionAnswers)
        {
            try
            {
                return accountDao.InsertUserAnswers(lstQuestionAnswers);
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// CertificationDateUpdated - Updates certification date in the database
        /// for a provided UserId
        /// 
        /// PreConditions:
        /// User must exist in the system
        /// 
        /// PostConditions:
        /// Returns boolean value for success status on update
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public bool CertificationDateUpdated(User user)
        {
            try
            {
                return (accountDao.UpdateCertificationDate(user.UserId) > 0);
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// DisclaimerDateUpdated - Updates disclaimer date in the database
        /// for a provided UserId
        /// 
        /// PreConditions:
        /// User must exist in the system
        /// 
        /// PostConditions:
        /// Returns boolean value for success status on update
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public bool DisclaimerDateUpdated(User user)
        {
            try
            {
                return (accountDao.UpdateDisclaimerDate(user.UserId) > 0);
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// CertificationDateUpdated - Retrieves certification date in the database
        /// for a provided UserId to establish that answers are certified
        /// 
        /// PreConditions:
        /// User must exist in the system
        /// 
        /// PostConditions:
        /// Returns boolean value for a date returned that is not the MinValue for DateTime
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public bool HasUserCertifiedAnswers(User user)
        {
            try
            {
                DateTime dtCertification = accountDao.GetCertificationDate(user.UserId);
                if (dtCertification != DateTime.MinValue)
                    return true;
                else
                    return false;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// GetAnswer - Retrieves question answer in the database
        /// for a provided UserId and question field name
        /// 
        /// PreConditions:
        /// User and question answer field name must exist in the system
        /// 
        /// PostConditions:
        /// Returns QuestionAnswer boject representing a question answer 
        /// for a field name and userId
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="fieldName"></param>
        /// <returns></returns>
        public QuestionAnswer GetAnswer(int userId, string fieldName)
        {
            try
            {
                return accountDao.GetUserAnswerByField(userId, fieldName);
            }
            catch (Exception)
            {
                return null;
            }
        }

        /// <summary>
        /// GetUserAnswers - Retrieves all question answers for a UserId
        /// 
        /// PreConditions:
        /// User needs to exist in the system
        /// 
        /// PostConditions:
        /// List of question answers is returned
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public List<QuestionAnswer> GetUserAnswers(int userId)
        {
            try
            {
                return accountDao.GetUserAnswers(userId);
            }
            catch (Exception)
            {
               return new List<QuestionAnswer>();
            }
        }

        /// <summary>
        /// GetAdminUser - Retireves User object for administation request
        /// 
        /// PreConditions:
        /// None
        /// 
        /// PostConditions:
        /// User object is returned based on parameters passed
        /// </summary>
        /// <param name="username"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public User GetAdminUser(string username, string password)
        {
            User user;

            try
            {
                user = accountDao.GetUserInfo(username, password);
            }
            catch (Exception ex)
            {
                user = null;
            }

            return user;
        }

        /// <summary>
        /// GetCategories - Retrieves all Question Categories from the database
       /// 
        /// PreConditions:
        /// None
        /// 
        /// PostConditions:
        /// List of question category objects is returned
        /// </summary>
        /// <returns></returns>
        public List<QuestionCategory> GetCategories()
        {
            try
            {
                return accountDao.GetCategories();
            }
            catch (Exception)
            {
                return new List<QuestionCategory>();
            }

        }

        /// <summary>
        /// InsertCategory - Adds a category to the database
        /// 
        /// PreConditions:
        /// None
        /// 
        /// PostConditions:
        /// Returns identity value if category was added successfully
        /// </summary>
        /// <param name="CategoryDescription"></param>
        /// <returns></returns>
        public int InsertCategory(string CategoryDescription)
        {
            try
            {
                return accountDao.InsertCategory(CategoryDescription);
            }
            catch (Exception)
            {
                return 0;
            }
        }

        /// <summary>
        /// UpdateCategory - Updates category in the database
        /// 
        /// PreConditions:
        /// category needs to exist in the database
        /// 
        /// PostConditions:
        /// Returns boolean value for success status on update
        /// </summary>
        /// <param name="categoryId"></param>
        /// <param name="categoryDescription"></param>
        /// <returns></returns>
        public bool UpdateCategory(int categoryId, string categoryDescription)
        {
            try
            {
                return accountDao.UpdateCategory(categoryId, categoryDescription);
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// DeleteCategory - Deletes category in the database
        /// 
        /// PreConditions:
        /// category needs to exist in the database
        /// 
        /// PostConditions:
        /// Returns boolean value for success status on delete
        /// </summary>
        /// <param name="categoryId"></param>
        /// <returns></returns>
        public bool DeleteCategory(int categoryId)
        {
            try
            {
                return accountDao.DeleteCategory(categoryId);
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// GetQuestionById - Retrieves Question from the database
        /// related to the provided questionId value
        /// 
        /// PreConditions:
        /// Question needs to exist in the system
        /// 
        /// PostConditions:
        /// Question objects is returned
        /// </summary>
        /// <param name="questionId"></param>
        /// <returns></returns>
        public Question GetQuestionById(int questionId)
        {
            try
            {
                return accountDao.GetQuestionById(questionId);
            }
            catch (Exception ex)
            {
                return new Question();
            }

        }

        /// <summary>
        /// UpdateQuestionCore - Updates question core fields in the database
        /// 
        /// PreConditions:
        /// Question needs to exist in the database
        /// 
        /// PostConditions:
        /// Returns boolean value for success status on update
        /// </summary>
        /// <param name="questionId"></param>
        /// <param name="questionCategoryId"></param>
        /// <param name="questionSortOrder"></param>
        /// <param name="displayType"></param>
        /// <param name="fieldLabel"></param>
        /// <param name="fieldCss"></param>
        /// <param name="fieldSuffix"></param>
        /// <param name="fieldHelpText"></param>
        /// <param name="fieldHelpUrl"></param>
        /// <returns></returns>
        public bool UpdateQuestionCore(int questionId, int questionCategoryId, int questionSortOrder, string displayType,
                                  string fieldLabel, string fieldCss, string fieldSuffix, string fieldHelpText, string fieldHelpUrl)
        {
            try
            {
                return (accountDao.UpdateQuestion(questionId, questionCategoryId, questionSortOrder, displayType,
                                                 fieldLabel, fieldCss, fieldSuffix, fieldHelpText, fieldHelpUrl) > 0);
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// UpdateQuestionStatus - Updates Question status from the database
        /// related to the provided questionId value
        /// 
        /// PreConditions:
        /// Question needs to exist in the system
        /// 
        /// PostConditions:
        /// Boolean value reflect update success is returned
        /// </summary>
        /// <param name="questionId"></param>
        /// <returns></returns>
        public bool UpdateQuestionStatus(int questionId)
        {
            try
            {
                return (accountDao.UpdateQuestionActiveStatus(questionId) > 0);
            }
            catch (Exception ex)
            {
                return false;
            }

        }

        /// <summary>
        /// UpdateQuestionStatusByValue - Updates Question status from the database
        /// related to the provided questionId value and active status value
        /// 
        /// PreConditions:
        /// Question needs to exist in the system
        /// 
        /// PostConditions:
        /// Boolean value reflect update success is returned
        /// </summary>
        /// <param name="questionId"></param>
        /// <returns></returns>
        public bool UpdateQuestionStatusByValue(int questionId, bool questionActive)
        {
            try
            {
                return (accountDao.UpdateQuestionActiveStatusByValue(questionId, questionActive) > 0);
            }
            catch (Exception ex)
            {
                return false;
            }

        }

        /// <summary>
        /// InsertQuestionCore - Inserts question core fields in the database
        /// 
        /// PreConditions:
        /// None
        /// 
        /// PostConditions:
        /// Returns identity value for insert
        /// </summary>
        /// <param name="questionCategoryId"></param>
        /// <param name="questionSortOrder"></param>
        /// <param name="displayType"></param>
        /// <param name="fieldName"></param>
        /// <param name="fieldLabel"></param>
        /// <param name="fieldCss"></param>
        /// <param name="fieldSuffix"></param>
        /// <param name="fieldHelpText"></param>
        /// <param name="fieldHelpUrl"></param>
        /// <returns></returns>
        public int InsertQuestionCore(int questionCategoryId, int questionSortOrder, string displayType, string fieldName,
                                  string fieldLabel, string fieldCss, string fieldSuffix, string fieldHelpText, string fieldHelpUrl)
        {
            try
            {
                return accountDao.InsertQuestion(questionCategoryId, questionSortOrder, displayType, fieldName,
                                                 fieldLabel, fieldCss, fieldSuffix, fieldHelpText, fieldHelpUrl);
            }
            catch (Exception)
            {
                return 0;
            }
        }

        /// <summary>
        /// GetOptionsByQuestionId - Retrieves all question options for a QuestionId
        /// 
        /// PreConditions:
        /// Question needs to exist in the system
        /// 
        /// PostConditions:
        /// List of question options is returned
        /// </summary>
        /// <param name="questionId"></param>
        /// <returns></returns>
        
        public List<QuestionOption> GetOptionsByQuestionId(int questionId)
        {
            try
            {
                return accountDao.GetQuestionOptions(questionId);
            }
            catch (Exception ex)
            {
                return new List<QuestionOption>();
            }
        }

        /// <summary>
        /// UpdateOption - Updates question option fields in the database
        /// 
        /// PreConditions:
        /// Option needs to exist in the database
        /// 
        /// PostConditions:
        /// Returns integer value for success status on update
        /// </summary>
        public int UpdateOption(QuestionOption questionOption)
        {
            int nReturn = 0;

            try
            {
                accountDao.UpdateQuestionOptionCore(questionOption.Id, questionOption.SortOrder, questionOption.Name,  questionOption.OptionLabel, 
                    questionOption.OptionCSS, questionOption.OptionHelpURL, 1);

                foreach (OptionSpecial optionSpecial in questionOption.Specials)
                {
                    accountDao.UpdateQuestionOptionSpecialCore(optionSpecial.Id,
                                                               optionSpecial.Name,
                                                               optionSpecial.DisplayType,
                                                               questionOption.Id);
                }

                nReturn = 1;
            }
            catch (Exception)
            {
                nReturn = 0;
            }

            return nReturn;
        }

        /// <summary>
        /// InsertOptionCore - Inserts question option fields in the database
        /// 
        /// PreConditions:
        /// None
        /// 
        /// PostConditions:
        /// Returns integer value for success status on update
        /// </summary>
        internal int InsertOptionCore(QuestionOption questionOption, int questionId)
        {
            int nReturn = 0;

            try
            {
                int nIdentity = accountDao.InsertQuestionOptionCore(questionOption.SortOrder, questionOption.Name, questionOption.OptionLabel,
                    questionOption.OptionCSS, questionOption.OptionHelpURL, questionId);

                foreach (OptionSpecial optionSpecial in questionOption.Specials)
                {
                    accountDao.InsertQuestionOptionSpecialCore(nIdentity,
                                                               optionSpecial.Name,
                                                               optionSpecial.DisplayType);
                }

                nReturn = 1;
            }
            catch (Exception)
            {
                nReturn = 0;
            }

            return nReturn;
        }

        /// <summary>
        /// UpdateOptionStatusByValue - Updates Question Option status from the database
        /// related to the provided optionId value and active status value
        /// 
        /// PreConditions:
        /// Option needs to exist in the system
        /// 
        /// PostConditions:
        /// Boolean value reflect update success is returned
        /// </summary>
        /// <param name="optionId"></param>
        /// <param name="optionActive"></param>
        /// <returns></returns>
        public bool UpdateOptionStatusByValue(int optionId, bool optionActive)
        {
            try
            {
                return (accountDao.UpdateOptionActiveStatusByValue(optionId, optionActive) > 0);
            }
            catch (Exception ex)
            {
                return false;
            }
        }
    }
}